
#ifndef PRINT_H
#define PRINT_H
#include<memory>
#include <cstdio>  //采用C风格精细控制输出格式
#include "../BTree/BTree.h"  //B树
static void print(const char* x) { printf(" %s", x ? x : "<NULL>"); }  //字符串特别处理
class UniPrint {
   public:
    void static p(int e) { printf(" %04d", e); }
    void static p(float e) { printf(" %4.3f", e); }
    void static p(double e) { printf(" %4.3f", e); }
    void static p(char e) { printf(" %c", (31 < e) && (e < 128) ? e : '$'); }
    template <typename T>
    static void p(const BTree<T>&);  // B-树
    template <typename T>
    static void p(T* s)  //所有指针
    {
        s ? p(*s) : print("<NULL>");
    }  //统一转为引用

};  // UniPrint

/******************************************************************************************
 * 数据元素、数据结构通用输出接口
 ******************************************************************************************/
template <typename T>
static void print(const T* x)
{
    x ? print(*x) : printf(" <NULL>");
}
template <typename T>
static void print(const T& x)
{
    UniPrint::p(x);
}

#pragma once

/******************************************************************************************
 * BTree输出打印
 ******************************************************************************************/
#include "../BitMap/Bitmap.h"  //使用位图记录分支转向

/******************************************************************************************
 * BTree打印（递归）
 ******************************************************************************************/
#include <iostream>
template <typename T>  //元素类型
static void printBTree(T bt, int depth, bool isLeftmost, bool isRightmost, Bitmap* leftmosts,
                       Bitmap* rightmosts)
{
    setbuf(stdout, NULL);  // debug
    if (!bt) return;
    isLeftmost ? leftmosts->set(depth) : leftmosts->clear(depth);  //设置或清除当前层的拐向标志
    isRightmost ? rightmosts->set(depth) : rightmosts->clear(depth);  //设置或清除当前层的拐向标志
    int k = bt->child.size() - 1;  //找到当前节点的最右侧孩子，并
    printBTree(bt->child[k].get(), depth + 1, false, true, leftmosts, rightmosts);  //递归输出之
    bool parentOK = false;
    T p = bt->parent;
    if (!p)
        parentOK = true;
    else
        for (int i = 0; i < p->child.size(); i++)
            if (p->child[i].get() == bt) parentOK = true;
    while (0 < k--) {  //自右向左，输出各子树及其右侧的关键码
        /*DSA*/ printf(parentOK ? " " : "X");
        print(bt->key[k]);
        printf(" *>");
        for (int i = 0; i < depth; i++)  //根据相邻各层
            (leftmosts->test(i) && leftmosts->test(i + 1) ||
             rightmosts->test(i) && rightmosts->test(i + 1))
                ?  //的拐向是否一致，即可确定
                printf("      ")
                : printf("│    ");  //是否应该打印横向联接线

        if (((0 == depth && 1 < bt->key.size()) || !isLeftmost && isRightmost) &&
            bt->key.size() - 1 == k)
            printf("┌─");
        else if (((0 == depth && 1 < bt->key.size()) || isLeftmost && !isRightmost) && 0 == k)
            printf("└─");
        else
            printf("├─");
        print(bt->key[k]);
        printf("\n");
        printBTree(bt->child[k].get(), depth + 1, 0 == k, false, leftmosts,
                   rightmosts);  //递归输出子树
    }
}
/******************************************************************************************
 * BTree打印（入口）
 ******************************************************************************************/

template <typename T>  //元素类型
void UniPrint::p(const BTree<T>& bt)
{                   
                                                     //引用
    printf("%s[%p]*%d:\n", typeid(bt).name(), (void*)&bt, bt.size());  //基本信息
    auto leftmosts{std::make_unique<Bitmap>()} ;   //记录当前节点祖先的方向
    auto rightmosts {std::make_unique<Bitmap>()};  //记录当前节点祖先的方向
    printBTree(bt.root(), 0, true, true, leftmosts.get(), rightmosts.get());  //输出树状结构
    printf("\n");
}
#endif